package domain

import (
	"crypto/md5"
	"fmt"

	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/x/errors"

	"go-weixin/common/chendb"
	"go-weixin/common/utils"
	"io"
	"time"

	"go-weixin/app/music/model"
	"go-weixin/app/music/musicrpc/internal/dao"
	"go-weixin/app/music/musicrpc/internal/repo"
	"go-weixin/app/music/musicrpc/pb/proto/music"
)

type MusicDomain struct {
	musicRepo repo.MusicRepo
	ut        utils.Utils
}

func NewMusicDomain(engine chendb.ChenDb) *MusicDomain {
	return &MusicDomain{
		musicRepo: dao.NewMusicDao(engine),
		ut:        *utils.UT,
	}
}

func (d MusicDomain) MusicFileStreamUpload(stream music.Music_MusicStreamDataServer, goFastDns string) error {
	var fileByte []byte
	req := &music.MusicStreamDataReq{}
	res := &music.MusicStreamDataResp{}
	for {
		da, err := stream.Recv()

		if (da != nil) && (len(da.FileByte) > 0) {
			fileByte = append(fileByte, da.GetFileByte()...)
		}
		if err == io.EOF {
			fileName := ""
			var fileSize int64
			if req.Filename == "" {
				fileName = time.Now().Local().Format("20060102150405")
			} else {
				fileName = req.Filename
			}
			if req.Size == 0 {
				fileSize = int64(len(fileByte))
			} else {
				fileSize = req.Size
			}

			fileHash := fmt.Sprintf("%x", md5.Sum(fileByte))
			music := &model.MusicModel{}
			has, err := d.musicRepo.MusicGetByMd5(fileHash, music)
			if err != nil {
				return err
			}
			if has {
				res.Domain = goFastDns
				res.Md5 = music.Md5
				res.Path = music.Path
				res.Pictrue = music.Pictrue
				res.Size = music.Size
				stream.SendAndClose(res)
				return nil
			}
			musicInfo, err := d.MusicReadTagInfo(fileByte, fileName, fileSize)
			if err != nil {
				return errors.New(8000, "获取音乐info异常:"+err.Error())
			}
			PictrueGoFastResp, err := d.ut.GoFastDfs.GoFastDfsClient(musicInfo.PictrueData, musicInfo.Title, int64(len(musicInfo.PictrueData)), goFastDns)
			if err != nil {
				return errors.New(8000, "音乐封面上传异常:"+err.Error())
			}
			goFastResp, err := d.ut.GoFastDfs.GoFastDfsClient(fileByte, fileName, fileSize, goFastDns)
			if err != nil {
				return errors.New(8000, "音乐文件上传异常:"+err.Error())
			}

			err = d.MusicAdd(musicInfo.Title, musicInfo.Artist, goFastResp.Path, goFastResp.Md5, int64(musicInfo.Year), musicInfo.Vendor, PictrueGoFastResp.Path, musicInfo.FileType, musicInfo.PictrueExc, fileSize, "music.add")
			if err != nil {
				return errors.New(8000, "音乐添加异常:"+err.Error())
			}
			res.Domain = goFastResp.Domain
			res.Md5 = goFastResp.Md5
			res.Path = goFastResp.Path
			res.Pictrue = PictrueGoFastResp.Path
			res.Size = goFastResp.Size
			stream.SendAndClose(res)
			return nil
		}
		if err != nil {
			stream.SendAndClose(res)
			return errors.New(8000, "rpc流返回异常:"+err.Error())
		}
		req.Filename = da.GetFilename()
		req.Size = da.GetSize()
	}
}

func (d MusicDomain) MusicMd5Exist(md5 string) (*model.MusicModel, error) {
	music := &model.MusicModel{}
	has, err := d.musicRepo.MusicGetByMd5(md5, music)
	if err != nil {
		return nil, err
	}
	if !has {
		return nil, nil
	}
	return music, nil
}

func (d MusicDomain) MusicAdd(title string, artist string, path string, md5 string, year int64, vendor string, Pictrue string, fileType string, imgExt string, size int64, desc string) error {
	music := &model.MusicModel{
		Title:    title,
		Artist:   artist,
		Path:     path,
		Md5:      md5,
		Year:     year,
		Vendor:   vendor,
		Pictrue:  Pictrue,
		FileType: fileType,
		ImgExt:   imgExt,
		Size:     size,
		Desc:     desc,
	}
	affected, err := d.musicRepo.MusicAdd(music)
	if err != nil {
		return errors.New(8000, "music.add数据库异常:"+err.Error())
	}
	if affected == 0 {
		return errors.New(8000, "music.add添加行数为0:"+err.Error())
	}
	return nil
}

func (d MusicDomain) MusicReadTagInfo(fileByte []byte, fileName string, fileSize int64) (*utils.AutioTagInfo, error) {
	// 解析tag
	musicInfo, err := d.ut.Autio.AutioTagRead(fileByte, fileSize, "music")
	if err != nil {
		return nil, errors.New(8000, "音乐tag读取异常:"+err.Error())
	}
	// b := make([]byte, fileSize)
	h := fmt.Sprintf("%x", md5.Sum(fileByte))
	logx.Infof("文件md5值: %s", h)
	return musicInfo, nil
}

func (d MusicDomain) MusicList(page int64) ([]model.MusicModel, error) {
	limit := 10
	offset := 10 * (page - 1)
	musicList := make([]model.MusicModel, 0)
	err := d.musicRepo.MusicList(int64(limit), offset, &musicList)
	if err != nil {
		return nil, err
	}
	return musicList, nil
}

func (d MusicDomain) MusicDelete(md5 string) error {
	affected, err := d.musicRepo.MusicDeleteByMd5(md5)
	if err != nil {
		return err
	}
	if affected == 0 {
		return errors.New(8000, "删除行数为0")
	}
	return nil
}

func (d MusicDomain) MusicQueryTitle(title string, page int64) ([]model.MusicModel, error) {
	musicList := make([]model.MusicModel, 0)
	limit := 10
	offset := 10 * (page - 1)
	err := d.musicRepo.MusicLikeByTitle(title, limit, int(offset), &musicList)
	if err != nil {
		return nil, err
	}
	return musicList, nil
}

func (d MusicDomain) MusicQueryArtist(artist string, page int64) ([]model.MusicModel, error) {
	musicList := make([]model.MusicModel, 0)
	limit := 10
	offset := 10 * (page - 1)
	err := d.musicRepo.MusicLikeByArtist(artist, limit, int(offset), &musicList)
	if err != nil {
		return nil, err
	}
	return musicList, nil
}

// goFastResp := new(utils.GoFastDfsResp)
// err = json.Unmarshal(pictrueResByte, goFastResp)
// if err != nil {
// 	return nil, nil, err
// }
// music := &model.MusicModel{
// 	Title:    musicInfo.Title,
// 	Artist:   musicInfo.Artist,
// 	Year:     int64(musicInfo.Year),
// 	Vendor:   musicInfo.Vendor,
// 	FileType: musicInfo.FileType,
// 	Pictrue:  goFastResp.Path,
// 	ImgExt:   musicInfo.PictrueExc,
// 	Size:     fileSize,
// 	Desc:     "music",
// }

// // 保存信息
// affected, err := d.musicRepo.MusicAdd(music)
// if err != nil {
// 	return errors.New(8000, "添加Music.model异常:"+err.Error())
// }
// if affected == 0 {
// 	return errors.New(8000, "添加Music.model添加数为0")
// }
